package com.cloudbroker.bcs.common.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class StringUtil {
    
    public static final String EMPTY_STRING = "";
    
    public static final String[] EMPTY_STRING_ARR = new String[0];
    
    private static final Logger LOGGER = LoggerFactory.getLogger(StringUtil.class);
    
    private static Pattern BLANK_PATTERN = Pattern.compile("\\s");
    
    private static Pattern UPPER_CASE_PATTERN = Pattern.compile("([A-Z])");
    
    private static Method propertiesSaveConvertMethod;
    private static Properties dummyProperties;
    
    static {
        init();
    }
    
    private static void init() {
        try {
            propertiesSaveConvertMethod = Properties.class.getDeclaredMethod("saveConvert", new Class[] {
                    String.class, Boolean.TYPE, Boolean.TYPE });
            propertiesSaveConvertMethod.setAccessible(true);
            dummyProperties = new Properties();
        } catch (Exception e) {
            LOGGER.error("init propertiesSaveConvertMethod failed", e);
        }
    }
    
    public static boolean isEmpty(String str) {
        return null == str || 0 == str.length();
    }
    
    public static boolean isBlank(String str) {
        if (null == str || 0 == str.length()) {
            return true;
        }
        int len = str.length();
        for (int i = 0; i < len; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }
    
    public static String nullSafeTrim(String str) {
        return null == str ? null : str.trim();
    }
    
    public static String emptyToNull(Object value) {
        if (null == value) {
            return null;
        } else {
            String str = String.valueOf(value);
            if (str.isEmpty()) {
                return null;
            } else {
                return str;
            }
        }
    }
    
    public static String nullToEmpty(Object value) {
        return null == value ? EMPTY_STRING : String.valueOf(value);
    }
    
    public static String[] splitUsingIndex(String source, String sep) {
        return splitUsingIndex(source, sep, false);
    }
    
    public static String[] splitUsingIndex(String source, String sep, boolean keepLastEmpty) {
        if (null == source || null == sep || source.isEmpty()) {
            return EMPTY_STRING_ARR;
        }
        List<String> list = new ArrayList<String>();
        int sourceLen = source.length();
        int sepLen = sep.length();
        int fromIdx = 0;
        int idx = 0;
        while (-1 != (idx = source.indexOf(sep, fromIdx))) {
            list.add(source.substring(fromIdx, idx));
            fromIdx = idx + sepLen;
            if (fromIdx == sourceLen) {
                break;
            }
        }
        if (fromIdx == sourceLen) {
            if (keepLastEmpty) {
                list.add(EMPTY_STRING);
            }
        } else {
            list.add(source.substring(fromIdx));
        }
        return list.toArray(new String[list.size()]);
    }
    
    public static String[] splitUsingIndex(String source, char sep) {
        return splitUsingIndex(source, sep, false);
    }
    
    public static String[] splitUsingIndex(String source, char sep, boolean keepLastEmpty) {
        if (null == source) {
            return EMPTY_STRING_ARR;
        } else if (source.isEmpty()) {
            return new String[] { EMPTY_STRING };
        }
        List<String> list = new ArrayList<String>();
        int sourceLen = source.length();
        int sepLen = 1;
        int fromIdx = 0;
        int idx = 0;
        while (-1 != (idx = source.indexOf(sep, fromIdx))) {
            list.add(source.substring(fromIdx, idx));
            fromIdx = idx + sepLen;
            if (fromIdx == sourceLen) {
                break;
            }
        }
        if (fromIdx == sourceLen) {
            if (keepLastEmpty) {
                list.add(EMPTY_STRING);
            }
        } else {
            list.add(source.substring(fromIdx));
        }
        return list.toArray(new String[list.size()]);
    }
    
    public static Integer[] splitToInteger(String source, String splitRegex) {
        String[] strArr = source.split(splitRegex);
        int arrLen = strArr.length;
        Integer[] intArr = new Integer[arrLen];
        for (int i = 0; i < arrLen; i++) {
            intArr[i] = Integer.valueOf(strArr[i].trim());
        }
        return intArr;
    }
    
    public static int[] splitToInt(String source, String splitRegex) {
        String[] strArr = source.split(splitRegex);
        int arrLen = strArr.length;
        int[] intArr = new int[arrLen];
        for (int i = 0; i < arrLen; i++) {
            intArr[i] = Integer.parseInt(strArr[i]);
        }
        return intArr;
    }
    
    public static Long[] splitToLong(String source, String splitRegex) {
        String[] strArr = source.split(splitRegex);
        int arrLen = strArr.length;
        Long[] longArr = new Long[arrLen];
        for (int i = 0; i < arrLen; i++) {
            longArr[i] = Long.valueOf(strArr[i]);
        }
        return longArr;
    }
    
    public static long[] splitToLon(String source, String splitRegex) {
        String[] strArr = source.split(splitRegex);
        int arrLen = strArr.length;
        long[] longArr = new long[arrLen];
        for (int i = 0; i < arrLen; i++) {
            longArr[i] = Long.parseLong(strArr[i]);
        }
        return longArr;
    }
    
    public static String toPropertiesValue(String rawString) {
        if (null != propertiesSaveConvertMethod) {
            try {
                return (String) propertiesSaveConvertMethod.invoke(dummyProperties, rawString, false, true);
            } catch (Exception e) {
                LOGGER.error("call propertiesSaveConvertMethod failed", e);
            }
        }
        return simpleToPropertiesValue(rawString);
    }
    
    private static String simpleToPropertiesValue(String rawString) {
        if (null != rawString && !rawString.isEmpty()) {
            int len = rawString.length();
            StringBuilder sBuilder = new StringBuilder(len * 2);
            for (int i = 0; i < len; i++) {
                char c = rawString.charAt(i);
                if (0x007e < c) {
                    sBuilder.append('\\').append('u').append(Integer.toHexString(c));
                } else {
                    sBuilder.append(c);
                }
            }
            return sBuilder.toString();
        } else {
            return rawString;
        }
    }
    
    public static String camelToUnderlineCase(String source, boolean toUpper) {
        if (null == source) {
            return null;
        }
        String result = camelToSeparateCase(source, '_');
        if (toUpper) {
            result = result.toUpperCase();
        }
        return result;
    }
    
    public static String camelToUnderlineCase(String source) {
        return camelToUnderlineCase(source, false);
    }
    
    public static String underlineToCamelCase(String source) {
        return toCamelCase(source, '_');
    }
    
    public static String toCamelCase(String s, char separator) {
        if (s == null) {
            return null;
        }
        s = s.toLowerCase();
        int len = s.length();
        StringBuilder sb = new StringBuilder(len);
        boolean upperCase = false;
        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            if (c == separator) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }
        
        return sb.toString();
    }
    
    public static String underlineToDot(String s) {
        return s.replaceAll("_", ".");
    }
    
    public static String camelToSeparateCase(String source, char separator) {
        if (null == source) {
            return null;
        }
        Matcher matcher = UPPER_CASE_PATTERN.matcher(source);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String g = matcher.group();
            matcher.appendReplacement(sb, separator + g.toLowerCase());
        }
        matcher.appendTail(sb);
        if (sb.charAt(0) == separator) {
            sb.delete(0, 1);
        }
        return sb.toString();
    }
    
    public static String stripAllBlank(String str) {
        return null == str ? null : BLANK_PATTERN.matcher(str).replaceAll("");
    }
    /**
    * @Title: isNumericAlphaChinese
    * @Description: 字符串是由数字、字符或中文组成
    * @param @param str
    * @param @return    
    * @return boolean    
    * @throws
     */
    public static boolean isNumericAlphaChinese(String str){
        if(str.length()==0) return false;
        boolean isNumbercAlphaChines=false;
        for(int i =0;i<str.length();i++){
            isNumbercAlphaChines=false;
            char charAt = str.charAt(i);
            if(Character.isDigit(charAt)){     
                isNumbercAlphaChines = true;   
            }
            if(Character.isLetter(charAt)){   
                isNumbercAlphaChines = true;
            } 
            if(isChinese(charAt)){
                isNumbercAlphaChines=true;
            }
            if(!isNumbercAlphaChines){
                return false;
            }
        }
        return true;
        
    }
    
    /**
    * @Title: isChinese
    * @Description: 判断中文汉字和符号
    * @param @param strName
    * @param @return    
    * @return boolean    
    * @throws
     */
    public static boolean isChinese(String strName) {
        char[] ch = strName.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            if (isChinese(c)) {
                return true;
            }
        }
        return false;
    }
    
    /**
    * @Title: isChinese
    * @Description: 根据Unicode编码完美的判断中文汉字和符号
    * @param @param c
    * @param @return    
    * @return boolean    
    * @throws
     */
    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
            return true;
        }
        return false;
    }

    public static String processPath(String path) {
        if( EnvironmentUtils.isOnWindows() ) {
            if( path.startsWith("/") ) {
                path = path.substring(1);
            }
        } else {
            if( !path.startsWith("/") ) {
                path = "/" + path;
            }
        }
        return path;
    }

    public static boolean startWithIgnoreCase(String src, String prefix) {
        src = ValueUtil.getString(src);
        prefix = ValueUtil.getString(prefix);
        return src.toLowerCase().startsWith(prefix.toLowerCase());
    }

    public static boolean containsIgnoreCase(String src, String containStr) {
        src = ValueUtil.getString(src);
        containStr = ValueUtil.getString(containStr);
        return src.toLowerCase().contains(containStr.toLowerCase());
    }
}
